/**
 * This class defines the client to send messages to different machines and connect to different servers. 
 */

/**
 * @author arpitagarwal
 * Copyright 2012, held by Arpit Agarwal, of University of Illinois at Urbana-Champaign. 
 */

package client;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

	Socket clientSocket; 
	String ipAddress; 
	int port; 
	DataInputStream inStream;
	DataOutputStream outStream; 
	private static PrintStream printStream = null;
    static BufferedReader inputLine = null;
    static boolean closed = false;
    private static final boolean PRINT_YES_NO = false;
    public boolean isServerAvail;  
    
    private boolean isServerAvail() {
		return isServerAvail;
	}

	private void setServerAvail(boolean isServerAvail) {
		this.isServerAvail = isServerAvail;
	}

	private DataOutputStream getOutStream() {
		return outStream;
	}

	@SuppressWarnings("unused")
	private void setOutStream(DataOutputStream outStream) {
		this.outStream = outStream;
	}

	private DataInputStream getInStream() {
		return inStream;
	}

	@SuppressWarnings("unused")
	private void setInStream(DataInputStream inputStream) {
		this.inStream = inputStream;
	}

	private Socket getClientSocket() {
		return clientSocket;
	}

	public String getIpAddress() {
		return ipAddress;
	}

	public int getPort() {
		return port;
	}

	private void setClientSocket(Socket clientSocket) {
		this.clientSocket = clientSocket;
	}

	private void setIpAddress(String ipAddress) {
		this.ipAddress = ipAddress;
	}

	private void setPort(int port) {
		this.port = port;
	}

	public boolean isConnectionDead() {
		boolean statusConnection = true; 
		try {
			if (getClientSocket().isClosed()) {
				statusConnection = true;
			} else {
				statusConnection = false;
			}
		} catch (Exception e) {
			Client.printClient("Couldn't close connection. Client socket is not defined."); 
		}
		return statusConnection;
	}
	
	public Client(String ip, int port) {
		setIpAddress(ip); 
		setPort(port);
		isServerAvail = true; 
		try {
			setClientSocket(new Socket(ip, port));
            Client.setPrintStream(new PrintStream(clientSocket.getOutputStream()));
            this.inStream = new DataInputStream(clientSocket.getInputStream());
            this.outStream = new DataOutputStream(clientSocket.getOutputStream()); 
		} catch (UnknownHostException e) {
			System.out.println("Unknown Host"); 
			e.printStackTrace();
			isServerAvail = false; 
		} catch (IOException e) {
			System.out.println("Server down: " + ip + ":" + port); 
			isServerAvail = false; 
//			e.printStackTrace();
		} 
	}
	public void sendData(String sendString) {
		try {
			if (!this.isConnectionDead()) {
				printClient(sendString);
				sendString = appendSnEOM(sendString);
				getOutStream().write(sendString.getBytes());
				getOutStream().flush();
			} else {
//				this.destroyConnection(); 
			}
		} catch (IOException e) {
//			e.printStackTrace();
			this.destroyConnection(); 
		}
	}
	public String appendSnEOM(String str) {
		return ("#" + str + "$"); 
	}
	public static final void printClient(String str) {
		if(PRINT_YES_NO) {
			System.out.println("Client: " + str);
		}
	}
	public void destroyConnection() {
		try {
			getInStream().close();
			getOutStream().close(); 
			getClientSocket().close();
		} catch (IOException e) {
			e.printStackTrace();
		} 
	}

	public static PrintStream getPrintStream() {
		return printStream;
	}

	public static void setPrintStream(PrintStream printStream) {
		Client.printStream = printStream;
	}	
}
